<?php

namespace App\Services;

use App\Models\College;
use App\Models\YikaoSchoolProvinceScore;
use GuzzleHttp\Client;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\ErrorLogHandler;

class YikaoSchoolProvinceScoreSpiderService
{
    private $client;
    private $logger;
    private $batchSize = 50; // 每次处理的院校数量
    private $limit = 0; // 采集数量限制，0表示无限制

    public function __construct()
    {
        $this->client = new Client([
            'timeout' => 30,
            'headers' => [
                'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
            ],
            'proxy' => "http://127.0.0.1:1080"
        ]);

        $this->logger = new Logger('yikao_school-province-score');
        $logPath = dirname(__DIR__, 2) . '/storage/logs/yikao-school-province-score.log';
        $this->logger->pushHandler(new StreamHandler($logPath, Logger::DEBUG));
        $this->logger->pushHandler(new ErrorLogHandler());
    }

    /**
     * 设置采集数量限制
     * @param int $limit 最大采集数量，0表示无限制
     */
    public function setLimit(int $limit): void
    {
        $this->limit = max(0, $limit);
        $this->logger->info("设置采集数量限制", ['limit' => $this->limit]);
    }

    /**
     * 主采集方法
     */
    public function crawlAllColleges()
    {
        echo "=== 开始采集艺各省分数线数据 ===\n";
        echo "采集限制: " . ($this->limit > 0 ? $this->limit : '无限制') . "\n";
        $this->logger->info('开始采集所有院校的艺考各省分数线', [
            'limit' => $this->limit > 0 ? $this->limit : '无限制'
        ]);
        
        $page = 1;
        $collected = 0;
        while (true) {
            $colleges = College::query()->where('status', 0)
                ->skip(($page - 1) * $this->batchSize)
                ->take($this->batchSize)
                ->get(['school_id']);
            
            if ($colleges->isEmpty()) {
                $this->logger->info('所有院校采集完成', [
                    'total_collected' => $collected
                ]);
                break;
            }

            foreach ($colleges as $college) {
                if ($this->limit > 0 && $collected >= $this->limit) {
                    echo "[信息] 已达到采集数量限制: {$this->limit}\n";
                    $this->logger->info('已达到采集数量限制', [
                        'limit' => $this->limit,
                        'collected' => $collected
                    ]);
                    break 2;
                }

                try {
                    echo "[采集] 开始处理院校ID: {$college->school_id}\n";
                    $this->logger->info("开始采集院校ID: {$college->school_id}");
                    $this->crawlSchoolProvinceScore($college->school_id);
                    echo "[完成] 院校ID: {$college->school_id} 采集成功\n";
                    $this->logger->info("院校ID: {$college->school_id} 采集完成");
                    $collected++;
                } catch (\Exception $e) {
                    echo "[错误] 院校ID: {$college->school_id} 采集失败: " . $e->getMessage() . "\n";
                    $this->logger->error("院校ID: {$college->school_id} 采集失败: " . $e->getMessage());
                    continue;
                }
            }

            $page++;
            echo "[等待] 批次处理完成，等待1秒...\n";
            sleep(1); // 批次间隔
        }
        echo "=== 采集完成 ===\n";
        echo "总共采集院校数: {$collected}\n";
        if ($this->limit > 0) {
            echo "采集限制: {$this->limit}\n";
        }
    }

    /**
     * 采集单个院校的历年分数线
     * @throws \Exception
     */
    private function crawlSchoolProvinceScore($schoolId)
    {
        // 1. 获取院校配置信息
        $configUrl = "https://static-data.gaokao.cn/www/2.0/yk/school/{$schoolId}/dic/provincescore.json?a=www.gaokao.cn";
        $config = $this->fetchApiData($configUrl);
        
        if ($config['code'] !== '0000') {
            throw new \Exception("获取院校配置失败: {$config['message']}");
        }

        $data = $config['data'];
        
        // 2. 遍历省份->年份->类型->批次
        foreach ($data['province'] as $province) {
            $years = $data['year'][$province] ?? [];
            
            foreach ($years as $year) {
                $typeKey = "{$province}_{$year}";
                $types = $data['type'][$typeKey] ?? [];
                
                foreach ($types as $type) {
                    // 3. 构建采集URL
                    $scoreUrl = "https://static-data.gaokao.cn/www/2.0/yk/schoolprovinceindex/{$year}/{$schoolId}/{$province}/{$type}/1.json?a=www.gaokao.cn";

                    // 4. 采集招生计划数据
                    $scoreData = $this->fetchApiData($scoreUrl);

                    if ($scoreData['code'] !== '0000') {
                        $this->logger->warning("招生计划采集失败: {$scoreData['message']}, URL: {$scoreUrl}");
                        continue;
                    }

                    // 5. 保存数据
                    $this->saveSchoolProvinceScore($scoreData['data']['item'], $year);
                }
            }
        }
    }

    /**
     * 调用API获取数据
     */
    private function fetchApiData($url)
    {
        $this->logger->debug("请求API: {$url}");
        
        try {
            $response = $this->client->get($url);
            $data = json_decode($response->getBody(), true);
            
            if (json_last_error() !== JSON_ERROR_NONE) {
                throw new \Exception("JSON解析失败: " . json_last_error_msg());
            }
            
            return $data;
        } catch (\Exception $e) {
            throw new \Exception("API请求失败: " . $e->getMessage());
        }
    }

    /**
     * 保存招生计划
     */
    private function saveSchoolProvinceScore($items, $year)
    {
        if (empty($items)) {
            return;
        }

        $dataToInsert = [];
        foreach ($items as $item) {
            $dataToInsert[] = [
                'batch' => $item['batch'] ?? null,
                'batch_name' => $item['batch_name'] ?? null,
                'cate' => $item['cate'] ?? null,
                'cate_name' => $item['cate_name'] ?? null,
                'formula' => $item['formula'] ?? null,
                'province_id' => $item['province_id'] ?? null,
                'remark' => $item['remark'] ?? null,
                'school_id' => $item['school_id'] ?? null,
                'score' => $item['score'] ?? null,
                'score_section' => $item['score_section'] ?? null,
                'sg_info' => $item['sg_info'] ?? null,
                'sg_name' => $item['sg_name'] ?? null,
                'type' => $item['type'] ?? null,
                'year' => $year
            ];
        }

        try {
            YikaoSchoolProvinceScore::query()->insert($dataToInsert);
            College::query()->where('school_id', $item['school_id'])->update(['status' => 1]);
            $this->logger->info("成功保存 " . count($dataToInsert) . " 条专业分数数据");
        } catch (\Exception $e) {
            throw new \Exception("数据保存失败: " . $e->getMessage());
        }
    }
}
